package com.sjh;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author jack
 * @data 2020/9/4 2:54 下午
 */
public class CountdownLatchTest {


    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        final CountDownLatch cdOrder = new CountDownLatch(1);//1 一声令下，线程都同时开始
        final CountDownLatch cdAnswer = new CountDownLatch(3);//3 3个线程都完成后，再执行下一步
        for (int i = 0; i < 3; i++) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令");
                        /*
                         * await():
                         * 使当前线程在锁存器倒计数至零之前一直等待，除非线程被中断。
                         * 如果当前计数为零，则此方法立即返回。
                         * 如果当前计数大于零，则出于线程调度目的，将禁用当前线程，且在发生以下两种情况之一前，该线程将一直处于休眠状态：
                         * 1.由于调用 countDown() 方法，计数到达零；
                         * 2.或者 其他某个线程中断当前线程。
                         * 如果当前线程：在进入此方法时已经设置了该线程的中断状态；或者 在等待时被中断，
                         * 则抛出 InterruptedException，并且清除当前线程的已中断状态。
                         */
                        cdOrder.await();//线程阻塞在这里，main线程开始运行
                        System.out.println("线程" + Thread.currentThread().getName() + "已接受命令");
                        Thread.sleep((long) (Math.random() * 10000));
                        System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果");
                        cdAnswer.countDown();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            service.execute(runnable);
        }
        try {//main线程
            Thread.sleep((long) (Math.random() * 10000));
            System.out.println("线程" + Thread.currentThread().getName()
                    + "即将发布命令");
            /*
             * countDown():
             * 递减锁存器的计数，如果计数到达零，则释放所有等待的线程。
             * 如果当前计数大于零，则将计数减少。
             * 如果新的计数为零，出于线程调度目的，将重新启用所有的等待线程。
             * 如果当前计数等于零，则不发生任何操作。
             */
            cdOrder.countDown();//将cdOrder置0，启动上面的线程
            System.out.println("线程" + Thread.currentThread().getName()
                    + "已发送命令，正在等待结果");
            cdAnswer.await();//线程阻塞在这里，继续执行上面的线程
            System.out.println("线程" + Thread.currentThread().getName()
                    + "已收到所有响应结果");
        } catch (Exception e) {
            e.printStackTrace();
        }
        service.shutdown();

    }

}
